package org.example.yuaiagent.app;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.example.yuaiagent.advisor.MyLoggerAdvisor;
import org.example.yuaiagent.chatmemory.MysqlChatMemory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.List;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;
@Component
@Slf4j
public class TravelApp {
    //系统提示词
    private static final String SYSTEM_PROMPT = "你是一位精通旅游规划和 AI 技术的专家，对国内外热门旅游城市有着深入的了解，"+
            "能够为用户提供专业、实用的旅游建议、"+
            "擅长将复杂的旅游需求转化为简洁明了的规划方案。";
    private final ChatClient chatClient;

    public TravelApp(ChatModel dashscopeChatModel, MysqlChatMemory mysqlChatMemory){
        System.out.println("+++++++++++++"+mysqlChatMemory);
                // 初始化基于文件的对话记忆
        String fileDir = System.getProperty("user.dir") + "/tmp/chat-memory";
//        ChatMemory chatMemory = new FileBasedChatMemory(fileDir);
        // 初始化基于内存的对话记忆
        //初始化基于内存的对话记忆
//        InMemoryChatMemory inMemoryChatMemory = new InMemoryChatMemory();
        //初始化基于mysql的对话记忆
        chatClient = ChatClient.builder(dashscopeChatModel)
                .defaultSystem(SYSTEM_PROMPT)
                .defaultAdvisors(new MessageChatMemoryAdvisor(mysqlChatMemory))
                .build();
    }

    public String doChat(String message, String chatId) {
         ChatResponse response = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .call()
                .chatResponse();
        if (response != null) {
            return response.getResult().getOutput().getText();
        };
        return null;
    }

    @Resource
    private VectorStore travelAppVectorStore;

//    @Resource(name="travelAppRagCloudVectorStore")
    @Resource
    private Advisor travelAppRagCloudAdvisor;

    @Resource
    private VectorStore pgVectorStore;

    // rag

     public String doChatWithRag(String message, String chatId) {
         ChatResponse response = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                 .advisors(new MyLoggerAdvisor())
//                 应用rag知识问答
//                  .advisors(new QuestionAnswerAdvisor(travelAppVectorStore))
//                 应用RAG检索增强服务（基于云知识库服务)
//                 .advisors(travelAppRagCloudAdvisor)
                 //基于本地向量数据库
                  .advisors(new QuestionAnswerAdvisor(pgVectorStore))

                .call()
                .chatResponse();
        String content = response.getResult().getOutput().getText();
         return content;
     }

    public Flux<String> doChatByStream(String message, String chatId) {
        return chatClient
                .prompt()
                .user(message)
                .tools(toolCallbackProvider)
                .tools(allTools)
                .advisors(new MyLoggerAdvisor())
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .stream()
                .content();
    }

    record TravelReport(String title, List<String> suggestions){};

//     static class TravelReport{
//         String title;
//         List<String> suggestions;
//     }

    /**
     * 结构化输出
     */
     public TravelReport doChatWithStructuredOutput(String message, String chatId) {
          TravelReport report= chatClient
                .prompt()
                  .system( SYSTEM_PROMPT+ "每次对话后，请根据用户的需求，生成一份旅游报告，并给出建议。标题为{用户名}的旅游报告，内容为建议列表")
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                 .advisors(new MyLoggerAdvisor())
                 .call()
                 .entity(TravelReport.class);
//                 应用rag知识问答
//                  .advisors(new QuestionAnswerAdvisor())
         return  report;

     }

     @Resource
     private ToolCallback[] allTools;

    /**
     * 调用工具
     */
    public String doChatWithTools(String message, String chatId) {
        ChatResponse chatResponse = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                // 开启日志，便于观察效果
                .advisors(new MyLoggerAdvisor())
                .tools(allTools)
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }

    @Resource
    private ToolCallbackProvider  toolCallbackProvider;

    /**
     * mcp
     */

    public String doChatWithMcp(String message, String chatId) {
        ChatResponse chatResponse = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                // 开启日志，便于观察效果
                .advisors(new MyLoggerAdvisor())
                .tools(toolCallbackProvider)
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }
}
